#ifndef __M_DB_H__
#define __M_DB_H__
#include "util.hpp"
#include "logerr.hpp"
#include <mutex>
#include <cassert>
#include <string>

class user_table
{

public:
    user_table(const std::string &host, const std::string &username, const std::string &password,
               const std::string &dbname, uint16_t port)
        : _mysql(mysql_util::mysql_create(host, username, password, dbname, port))
    {
        assert(_mysql != nullptr);
    }

    ~user_table()
    {
        mysql_util::mysql_destroy(_mysql);
    }

    bool insert(Json::Value &user)
    {
        if (user["username"].isNull() || user["password"].isNull())
        {
            DBG_LOG("insert error:%s", "username or password is null");
            return false;
        }
        std::lock_guard<std::mutex> lock(_mutex);
        // 转义用户名
        char sql[256] = {0};
        std::string username = user["username"].asString();
        std::string password = user["password"].asString();
        if(username==""||password=="") return false;
        snprintf(sql, sizeof(sql) - 1, "insert user values(null,'%s',password('%s'),1000,0,0);", username.c_str(), password.c_str());
        DBG_LOG("sql :%s", sql);
        bool n = mysql_util::mysql_exec(_mysql, std::string(sql));
        if (n == false)
        {
            DBG_LOG("insert error");
            return false;
        }
        return true;
    }

    bool login(Json::Value &user)
    {
        if (user["username"].isNull() || user["password"].isNull())
        {
            DBG_LOG("login error:%s", "username or password is null");
            return false;
        }
        MYSQL_RES *res = nullptr;
        {
            std::lock_guard<std::mutex> lock(_mutex);
            // 转义输入
            char sql[256] = {0};
            std::string username = user["username"].asString();
            std::string password = user["password"].asString();
            if(username==""||password=="") return false;
            snprintf(sql, sizeof(sql) - 1, "select id,score,total_count,win_count from user where username= '%s' and password=password('%s');",
                     username.c_str(), password.c_str());
            bool n = mysql_util::mysql_exec(_mysql, sql);
            if (n == false)
            {
                DBG_LOG("login error");
                return false;
            }
            res = mysql_store_result(_mysql);
            if (res == nullptr)
            {
                DBG_LOG("获取结果集错误");
                return false;
            }
            int row = mysql_num_rows(res);
            if (row == 0)
            {
                DBG_LOG("没有查询到相关数据");
                return false;
            }
            else if (row != 1)
            {
                DBG_LOG("查询结果不唯一");
                return false;
            }
        }
        MYSQL_ROW row = mysql_fetch_row(res);
        user["id"] = (Json::UInt64)std::stol(row[0]);
        user["score"] = (Json::UInt64)std::stol(row[1]);
        user["total_count"] = std::stoi(row[2]);
        user["win_count"] = std::stoi(row[3]);
        mysql_free_result(res);
        return true;
    }
    // 通过user带出去信息
    bool select_by_name(const std::string &name, Json::Value &user)
    {
        MYSQL_RES *res = nullptr;
        {
            std::lock_guard<std::mutex> lock(_mutex);
            char sql[256] = {0};
            snprintf(sql, sizeof(sql) - 1, "select id,score,total_count,win_count from user where username= '%s';", name.c_str());
            bool n = mysql_util::mysql_exec(_mysql, sql);
            if (n == false)
            {
                DBG_LOG("select_by_name error");
                return false;
            }
            res = mysql_store_result(_mysql);
            if (res == nullptr)
            {
                DBG_LOG("获取结果集错误");
                return false;
            }
            int row = mysql_num_rows(res);
            if (row == 0)
            {
                DBG_LOG("没有查询到相关数据");
                return false;
            }
            else if (row != 1)
            {
                DBG_LOG("查询结果不唯一");
                return false;
            }
        }
        MYSQL_ROW row = mysql_fetch_row(res);
        user["id"] = (Json::UInt64)std::stol(row[0]);
        user["score"] = (Json::UInt64)std::stol(row[1]);
        user["total_count"] = std::stoi(row[2]);
        user["win_count"] = std::stoi(row[3]);
        mysql_free_result(res);
        return true;
    }

    bool select_by_id(uint64_t id, Json::Value &user)
    {
        MYSQL_RES *res = nullptr;
        {
            std::lock_guard<std::mutex> lock(_mutex);
            char sql[256] = {0};
            snprintf(sql, sizeof(sql) - 1, "select username,score,total_count,win_count from user where id=%s;", std::to_string(id).c_str());
            bool n = mysql_util::mysql_exec(_mysql, sql);
            if (n == false)
            {
                DBG_LOG("select_by_id error");
                return false;
            }
            res = mysql_store_result(_mysql);
            if (res == nullptr)
            {
                DBG_LOG("获取结果集错误");
                return false;
            }
            int row = mysql_num_rows(res);
            if (row == 0)
            {
                DBG_LOG("没有查询到相关数据");
                return false;
            }
            else if (row != 1)
            {
                DBG_LOG("查询结果不唯一");
                return false;
            }
        }
        MYSQL_ROW row = mysql_fetch_row(res);
        user["id"] = (Json::UInt64)id;
        user["username"] = row[0];
        user["score"] = (Json::UInt64)std::stol(row[1]);
        user["total_count"] = std::stoi(row[2]);
        user["win_count"] = std::stoi(row[3]);
        mysql_free_result(res);
        return true;
    }

    bool win(uint64_t id)
    {
        Json::Value vv;
        if (select_by_id(id, vv) == false)
        {
            DBG_LOG("改id  %ld不存在", id);
            return false;
        }
        std::lock_guard<std::mutex> lock(_mutex);

        char sql[256] = {0};
        snprintf(sql, sizeof(sql) - 1, "update user set score=score+30,total_count=total_count+1, win_count=win_count+1 where id=%s;", std::to_string(id).c_str());
        bool n = mysql_util::mysql_exec(_mysql, sql);
        if (n == false)
        {
            DBG_LOG("win score error");
            return false;
        }
        return true;
    }

    bool lose(uint64_t id)
    {

        Json::Value vv;
        if (select_by_id(id, vv) == false)
        {
            DBG_LOG("改id %ld不存在", id);
            return false;
        }
        std::lock_guard<std::mutex> lock(_mutex);
       
        char sql[256] = {0};
        snprintf(sql, sizeof(sql) - 1, "update user set score=score-30,total_count=total_count+1 where id=%s;", std::to_string(id).c_str());
        DBG_LOG("%s", sql);
        bool n = mysql_util::mysql_exec(_mysql, sql);
        if (n == false)
        {
            DBG_LOG("lose socre error");
            return false;
        }
        return true;
    }

private:
    MYSQL *_mysql;
    std::mutex _mutex;
};
#endif